package com.atguigu.myssm.myspringmvc;

import com.atguigu.myssm.io.BeanFactory;
import com.atguigu.myssm.io.ClassPathXMLApplicationContext;
import com.atguigu.myssm.util.StringUtil;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

/**
 * @author 陆小根
 * date 2022-01-27
 */

// 拦截所有以.do结尾的请求
@WebServlet("*.do")
public class DispatcherServlet extends ViewBaseServlet {

    private BeanFactory beanFactory;

    public DispatcherServlet() {

    }

    public void init() throws ServletException {
        super.init();
        beanFactory = new ClassPathXMLApplicationContext();
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 设置编码
        req.setCharacterEncoding("UTF-8");


        // 假设url是：http://localhost:8080/fruitmvc/hello.do
        // 那么servletPath是：/hello.do
        // 我的思路是：
        // 第1步：/hello.do -> hello
        // -> HelloController
        // /hello.do -> hello 或者 .fruit.do -> fruit
        // 第2步： hello -> HelloController  或者 fruit -> FruitController1`
        String servletPath = req.getServletPath();
        System.out.println("servletPath = " + servletPath); // servletPath = /hello.do
        servletPath = servletPath.substring(1);
        int lastDotIndex = servletPath.lastIndexOf(".do");
        servletPath = servletPath.substring(0, lastDotIndex);

        Object controllerBeanObj = beanFactory.getBean(servletPath);

        String operate = req.getParameter("operate");
        if (StringUtil.isEmpty(operate)) {
            operate = "index"; // 如果operate没有值 默认为index
        }

        try {
            Method[] methods = controllerBeanObj.getClass().getDeclaredMethods();
            for (Method method : methods) {
                if (operate.equals(method.getName())) {
                    // 1.统一获取请求参数


                    // 1-1获取当前方法的参数，返回参数数组
                    Parameter[] parameters = method.getParameters();
                    // 1-2parameterValues用来存放参数的值
                    Object[] parameterValues = new Object[parameters.length];
                    for (int i = 0; i < parameters.length; i++) {
                        Parameter parameter = parameters[i];
                        String parameterName = parameter.getName();
                        // 如果参数名是request、response、session 那么就不是通过请求中获取参数的值
                        if ("request".equals(parameterName)) {
                            parameterValues[i] = req;
                        } else if ("response".equals(parameterName)) {
                            parameterValues[i] = resp;
                        } else if ("session".equals(parameterName)) {
                            parameterValues[i] = req.getSession();
                        } else {
                            // 从请求中获取参数值
                            String parameterValue = req.getParameter(parameter.getName());
                            String typeName = parameter.getType().getName();

                            Object parameterObj = parameterValue;

                            if (parameterObj != null) {
                                if ("java.lang.Integer".equals(typeName)) {
                                    parameterObj = Integer.parseInt(parameterValue);
                                }
                            }

                            parameterValues[i] = parameterObj; // "2" 而不是 2
                        }
                    }

                    // 2.controller组件中方法的调用
                    method.setAccessible(true);
                    Object returnObj = method.invoke(controllerBeanObj, parameterValues); // 调用当前实例

                    // 3.视图处理
                    String methodReturnStr = (String) returnObj;
                    if (methodReturnStr.startsWith("redirect:")) { // 比如：redirect:fruit.do
                        String redirectStr = methodReturnStr.substring("redirect:".length());
                        resp.sendRedirect(redirectStr);
                    } else {
                        super.processTemplate(methodReturnStr, req, resp); // 比如： "edit"
                    }
                }
            }

//
//            } else {
//                throw new RuntimeException("operate值非法");
//            }

        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

/*        // 获取当前类中所有的方法
        Method[] methods = controllerBeanObj.getClass().getDeclaredMethods();

        for (Method m : methods) {
            // 获取方法名称
            String methodName = m.getName();
            if (operate.equals(methodName)) {
                // 找到和operate同名的方法，那么通过反射技术调用它
                try {

                    return;
                } catch (IllegalAccessException | InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }*/


    }
}

// 常见错误：IllegalArgumentException：argument type mismatch